package com.yswee.framework.model;

import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.util.HashMap;

import com.yswee.framework.Application;
import com.yswee.framework.data.BaseArrayData;
import com.yswee.framework.data.parser.IParser;
import com.yswee.framework.net.ITask;
import com.yswee.framework.net.ITaskContext;
import com.yswee.framework.net.http.Callback;
import com.yswee.framework.net.http.Entity;
import com.yswee.framework.net.http.HttpFactory;
import com.yswee.framework.net.http.HttpType;
import com.yswee.framework.net.http.PostType;

import android.text.TextUtils;

public abstract class BaseListModel<T> {

	private WeakReference<ITaskContext> mContext;
	private IParser<BaseArrayData<T>> mParser;
	protected int mPageIndex = getFirstPageIndex();
	protected String mNextCursor = getFirtPageCursor();
	
	protected int getFirstPageIndex() {
		return 0;
	}
	
	protected String getFirtPageCursor() {
		return "";
	}
	
	protected ITaskContext getContext() {
		if(mContext != null) {
			return mContext.get();
		}
		return null;
	}
	
	protected boolean isCursorMode() {
		return false;
	}
	
	protected HttpType getHttpType() {
		return HttpType.Post;
	}
	
	public BaseListModel() {
		
	}
	
	public BaseListModel(ITaskContext context) {
		mContext = new WeakReference<ITaskContext>(context);
	}
	
	public boolean getFirstPage(boolean loadcache, Callback<BaseArrayData<T>> callback) {
		if(loadcache) {
			if(!getCacheData(callback != null ? callback.clone() : null)) {
				return false;
			}
		}
		if(callback != null) {
			callback.setPageType(PageType.FirstPage);
		}
		getPageData(callback);
		return true;
	}
	
	public void getNextPage(Callback<BaseArrayData<T>> callback) {
		if(callback != null) {
			callback.setPageType(PageType.NextPage);
		}
		getPageData(callback);
	}
	
	/**
	 * 从缓存获取数据
	 * @param callback
	 * @return true 继续从网络加载数据  false 不再加载网络数据
	 */
	public boolean getCacheData(Callback<BaseArrayData<T>> callback) {
		if(callback != null) {
			callback.setPageType(PageType.CachePage);
		}
		return true;
	}
	
	protected void getPageData(Callback<BaseArrayData<T>> c) {
		if(getHttpType() == HttpType.Post) {
			getPageDataPost(c);
		} else {
			getPageDataGet(c);
		}
	}
	
	protected void getPageDataGet(Callback<BaseArrayData<T>> c) {
		Entity<BaseArrayData<T>> entity = new Entity<BaseArrayData<T>>();
		entity.setBaseUrl(getWrapUrlGet(getUrl(c)));
		entity.setParser(getParser());
		entity.setContext(getContext());
		CallbackProxy<T> callback = getCallBackProxy(c);
		ITask task = HttpFactory.get().createHttp(entity, callback);
		task.excute();
	}
	
	protected void getPageDataPost(Callback<BaseArrayData<T>> c) {
		Entity<BaseArrayData<T>> entity = new Entity<BaseArrayData<T>>();
		entity.setBaseUrl(getWrapUrlPost(getUrl(c)));
		entity.setParser(getParser());
		entity.setContext(getContext());
		entity.setHttpType(HttpType.Post);
		entity.setPostType(PostType.TEXT);
		entity.setPostData(getWrapPostData(getPostData(c)));
		CallbackProxy<T> callback = getCallBackProxy(c);
		ITask task = HttpFactory.get().createHttp(entity, callback);
		task.excute();
	}
	
	protected String getUrl(Callback<BaseArrayData<T>> c) {
		if(isCursorMode()) {
			if(c.getPageType() == PageType.FirstPage) {
				return getUrl(c, getFirtPageCursor());
			} else {
				return getUrl(c, mNextCursor);
			}
		} else {
			if(c.getPageType() == PageType.FirstPage) {
				return getUrl(c, getFirstPageIndex());
			} else {
				return getUrl(c, mPageIndex);
			}
		}
	}
	
	protected String getUrl(Callback<BaseArrayData<T>> c, int pageIndex) {
		return null;
	}
	
	protected String getUrl(Callback<BaseArrayData<T>> c, String cursor) {
		return null;
	}
	
	protected String getWrapUrlGet(String url) {
		return url;
	}
	
	protected String getWrapUrlPost(String url) {
		return url;
	}
	
	public final IParser<BaseArrayData<T>> getParser() {
		if(mParser == null) {
			mParser = createParser();
		}
		return mParser;
	}
	
	protected abstract IParser<BaseArrayData<T>> createParser();
	
	protected HashMap<String, Object> getPostData(Callback<BaseArrayData<T>> c) {
		if(isCursorMode()) {
			if(c.getPageType() == PageType.FirstPage) {
				return getPostData(c, getFirtPageCursor());
			} else {
				return getPostData(c, mNextCursor);
			}
		} else {
			if(c.getPageType() == PageType.FirstPage) {
				return getPostData(c, getFirstPageIndex());
			} else {
				return getPostData(c, mPageIndex);
			}
		}
	}
	
	protected HashMap<String, Object> getPostData(Callback<BaseArrayData<T>> c, int pageIndex) {
		return null;
	}
	
	protected HashMap<String, Object> getPostData(Callback<BaseArrayData<T>> c, String cursor) {
		return null;
	}
	
	protected HashMap<String, Object> getWrapPostData(HashMap<String, Object> param) {
		return param;
	}
	
	protected CallbackProxy<T> getCallBackProxy(Callback<BaseArrayData<T>> c) {
		return new CallbackProxy<T>(BaseListModel.this, c);
	}
	
	protected void parsePagerData(BaseArrayData<T> data, PageType pageType) {
		if(isCursorMode()) {
			mNextCursor = data != null ? data.getPageCuror() : "";
		} else {
			if(pageType == PageType.FirstPage) {
				mPageIndex = getFirstPageIndex() + 1;
			} else {
				mPageIndex++;
			}
		}
	}
	
	public static class CallbackProxy<T> extends Callback<BaseArrayData<T>> {
		
		protected BaseListModel<T> mModel;
		protected Callback<BaseArrayData<T>> mCallback;

		@Override
		public void setPageType(PageType type) {
			if(mCallback != null) {
				mCallback.setPageType(type);
			}
		}

		@Override
		public PageType getPageType() {
			if(mCallback != null) {
				return mCallback.getPageType();
			} else {
				return PageType.FirstPage;
			}
		}
		
		public CallbackProxy(BaseListModel<T> model, Callback<BaseArrayData<T>> callback) {
			mModel = model;
			mCallback = callback;
		}
		
		@Override
		public BaseArrayData<T> onProcessData(Entity<BaseArrayData<T>> entity, String result) {
			if(mCallback != null)
				return mCallback.onProcessData(entity, result);
			else
				return super.onProcessData(entity, result);
		}

		@Override
		public void onFinish(Entity<BaseArrayData<T>> entity) {
			if(mCallback != null)
				mCallback.onFinish(entity);
			if(mModel != null) {
				mModel.parsePagerData(entity.getParsedData(), getPageType());
			}
		}

		@Override
		public void onError(Entity<BaseArrayData<T>> entity) {
			if(Application.get().getAppConfigure().getIsDebug()) {
				String json = getDebugJson();
				if(!TextUtils.isEmpty(json)) {
					entity.setParsedData(onProcessData(entity, json));
					onFinish(entity);
					return;
				}
			}
			if(mCallback != null)
				mCallback.onError(entity);
		}

		@Override
		public void onCancel(Entity<BaseArrayData<T>> entity) { 
			if(mCallback != null)
				mCallback.onCancel(entity);
		}
		
		@Override
		public void onInvalid(Entity<BaseArrayData<T>> entity) { 
			if(mCallback != null)
				mCallback.onInvalid(entity);
		}

		@Override
		public void onBeginResponse(HttpURLConnection connection) { 
			if(mCallback != null)
				mCallback.onBeginResponse(connection);
		}

		@Override
		public void onEndResponse(Entity<BaseArrayData<T>> entity) {
			if(mCallback != null)
				mCallback.onEndResponse(entity);
		}

		@Override
		public void onBeginRequest(Entity<BaseArrayData<T>> entity) {
			if(mCallback != null)
				mCallback.onBeginRequest(entity);
		}
		
		@Override
		public void onBeginConnection(HttpURLConnection connection) { 
			if(mCallback != null)
				mCallback.onBeginConnection(connection);
		}

		@Override
		public void onDownloadProgress(Entity<BaseArrayData<T>> entity) {
			if(mCallback != null)
				mCallback.onDownloadProgress(entity);
		}
		
		protected String getDebugJson() {
			return null;
		}
		
	}
	
}
